home *** CD-ROM | disk | FTP | other *** search
/ Amiga Games Extra 1996 September / Amiga Games Extra CD-ROM 9-1996.iso / userbox / publicdomain / vim-4.2 / src / message.c < prev    next >
C/C++ Source or Header  |  1996-06-16  |  19KB  |  832 lines

  1. /* vi:set ts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8.  
  9. /*
  10.  * message.c: functions for displaying messages on the command line
  11.  */
  12.  
  13. #include "vim.h"
  14. #include "globals.h"
  15. #define MESSAGE            /* don't include prototype for smsg() */
  16. #include "proto.h"
  17. #include "option.h"
  18.  
  19. static void msg_screen_outchar __ARGS((int c));
  20. static int msg_check_screen __ARGS((void));
  21.  
  22. static int    lines_left = -1;            /* lines left for listing */
  23.  
  24. /*
  25.  * msg(s) - displays the string 's' on the status line
  26.  * When terminal not initialized (yet) fprintf(stderr,..) is used.
  27.  * return TRUE if wait_return not called
  28.  */
  29.     int
  30. msg(s)
  31.     char_u           *s;
  32. {
  33.     msg_start();
  34.     if (msg_highlight)
  35.         start_highlight();
  36.     msg_outtrans(s);
  37.     if (msg_highlight)
  38.     {
  39.         stop_highlight();
  40.         msg_highlight = FALSE;        /* clear for next call */
  41.     }
  42.     msg_clr_eos();
  43.     return msg_end();
  44. }
  45.  
  46. /*
  47.  * automatic prototype generation does not understand this function
  48.  */
  49. #ifndef PROTO
  50. int smsg __ARGS((char_u *, long, long, long,
  51.                         long, long, long, long, long, long, long));
  52.  
  53. /* VARARGS */
  54.     int
  55. smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
  56.     char_u        *s;
  57.     long        a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
  58. {
  59.     sprintf((char *)IObuff, (char *)s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  60.     return msg(IObuff);
  61. }
  62. #endif
  63.  
  64. /*
  65.  * emsg() - display an error message
  66.  *
  67.  * Rings the bell, if appropriate, and calls message() to do the real work
  68.  * When terminal not initialized (yet) fprintf(stderr,..) is used.
  69.  *
  70.  * return TRUE if wait_return not called
  71.  */
  72.     int
  73. emsg(s)
  74.     char_u           *s;
  75. {
  76.     char_u            *Buf;
  77. #ifdef SLEEP_IN_EMSG
  78.     int                retval;
  79. #endif
  80.     static int        last_lnum = 0;
  81.     static char_u    *last_sourcing_name = NULL;
  82.  
  83.     if (emsg_off)                /* no error messages at the moment */
  84.         return TRUE;
  85.  
  86.     if (global_busy)            /* break :global command */
  87.         ++global_busy;
  88.  
  89.     if (p_eb)
  90.         beep_flush();            /* also includes flush_buffers() */
  91.     else
  92.         flush_buffers(FALSE);    /* flush internal buffers */
  93.     did_emsg = TRUE;            /* flag for DoOneCmd() */
  94.     ++msg_scroll;                /* don't overwrite a previous message */
  95.     (void)set_highlight('e');    /* set highlight mode for error messages */
  96.     msg_highlight = TRUE;
  97.     if (msg_scrolled)
  98.         need_wait_return = TRUE;    /* needed in case emsg() is called after
  99.                                      * wait_return has reset need_wait_return
  100.                                      * and a redraw is expected because
  101.                                      * msg_scrolled is non-zero */
  102.  
  103. /*
  104.  * First output name and line number of source of error message
  105.  */
  106.     if (sourcing_name != NULL &&
  107.            (sourcing_name != last_sourcing_name || sourcing_lnum != last_lnum)
  108.                                       && (Buf = alloc(MAXPATHL + 30)) != NULL)
  109.     {
  110.         ++no_wait_return;
  111.         if (sourcing_name != last_sourcing_name)
  112.         {
  113.             sprintf((char *)Buf, "Error detected while processing %s:",
  114.                                             sourcing_name);
  115.             msg(Buf);
  116.             msg_highlight = TRUE;
  117.         }
  118.             /* lnum is 0 when executing a command from the command line
  119.              * argument, we don't want a line number then */
  120.         if (sourcing_lnum != 0)
  121.         {
  122.             (void)set_highlight('n');    /* highlight mode for line numbers */
  123.             sprintf((char *)Buf, "line %4ld:", sourcing_lnum);
  124.             msg(Buf);
  125.             (void)set_highlight('e');    /* highlight mode for error messages */
  126.             msg_highlight = TRUE;
  127.         }
  128.         --no_wait_return;
  129.         last_lnum = sourcing_lnum;    /* only once for each line */
  130.         vim_free(Buf);
  131.     }
  132.     last_sourcing_name = sourcing_name;    /* do this also when it is NULL */
  133.  
  134. #ifdef SLEEP_IN_EMSG
  135. /*
  136.  * Msg returns TRUE if wait_return() was not called.
  137.  * In that case may call sleep() to give the user a chance to read the message.
  138.  * Don't call sleep() if dont_sleep is set.
  139.  */
  140.     retval = msg(s);
  141.     if (retval)
  142.     {
  143.         if (dont_sleep || need_wait_return)
  144.             need_sleep = TRUE;    /* sleep before removing the message */
  145.         else
  146.             mch_delay(1000L, TRUE);    /* give user chance to read message */
  147.     }
  148.     /* --msg_scroll;            don't overwrite this message */
  149.     return retval;
  150. #else
  151.     emsg_on_display = TRUE;        /* remember there is an error message */
  152.     return msg(s);
  153. #endif
  154. }
  155.  
  156.     int
  157. emsg2(s, a1)
  158.     char_u *s, *a1;
  159. {
  160.     /* Check for NULL strings (just in case) */
  161.     if (a1 == NULL)
  162.         a1 = (char_u *)"[NULL]";
  163.     /* Check for very long strings (can happen with ":help ^A<CR>") */
  164.     if (STRLEN(s) + STRLEN(a1) >= IOSIZE)
  165.         a1 = (char_u *)"[string too long]";
  166.     sprintf((char *)IObuff, (char *)s, (char *)a1);
  167.     return emsg(IObuff);
  168. }
  169.  
  170.     int
  171. emsgn(s, n)
  172.     char_u *s;
  173.     long    n;
  174. {
  175.     sprintf((char *)IObuff, (char *)s, n);
  176.     return emsg(IObuff);
  177. }
  178.  
  179. /*
  180.  * Like msg(), but truncate to a single line if p_shm contains 't'.
  181.  * Careful: The string may be changed!
  182.  */
  183.     int
  184. msg_trunc(s)
  185.     char_u    *s;
  186. {
  187.     int        n;
  188.  
  189.     if (shortmess(SHM_TRUNC) && (n = (int)STRLEN(s) -
  190.                     (int)(Rows - cmdline_row - 1) * Columns - sc_col + 1) > 0)
  191.     {
  192.         s[n] = '<';
  193.         return msg(s + n);
  194.     }
  195.     else
  196.         return msg(s);
  197. }
  198.  
  199. /*
  200.  * wait for the user to hit a key (normally a return)
  201.  * if 'redraw' is TRUE, clear and redraw the screen
  202.  * if 'redraw' is FALSE, just redraw the screen
  203.  * if 'redraw' is -1, don't redraw at all
  204.  */
  205.     void
  206. wait_return(redraw)
  207.     int        redraw;
  208. {
  209.     int                c;
  210.     int                oldState;
  211.     int                tmpState;
  212.  
  213.     if (redraw == TRUE)
  214.         must_redraw = CLEAR;
  215.  
  216. /*
  217.  * With the global command (and some others) we only need one return at the
  218.  * end. Adjust cmdline_row to avoid the next message overwriting the last one.
  219.  */
  220.     if (no_wait_return)
  221.     {
  222.         need_wait_return = TRUE;
  223.         cmdline_row = msg_row;
  224.         return;
  225.     }
  226.     oldState = State;
  227.     if (quit_more)
  228.     {
  229.         c = CR;                        /* just pretend CR was hit */
  230.         quit_more = FALSE;
  231.         got_int = FALSE;
  232.     }
  233.     else
  234.     {
  235.         State = HITRETURN;
  236. #ifdef USE_MOUSE
  237.         setmouse();
  238. #endif
  239.         if (msg_didout)                /* start on a new line */
  240.             msg_outchar('\n');
  241.         if (got_int)
  242.             MSG_OUTSTR("Interrupt: ");
  243.  
  244.         (void)set_highlight('r');
  245.         start_highlight();
  246. #ifdef ORG_HITRETURN
  247.         MSG_OUTSTR("Press RETURN to continue");
  248.         stop_highlight();
  249.         do {
  250.             c = vgetc();
  251.         } while (vim_strchr((char_u *)"\r\n: ", c) == NULL);
  252.         if (c == ':')                     /* this can vi too (but not always!) */
  253.             stuffcharReadbuff(c);
  254. #else
  255.         MSG_OUTSTR("Press RETURN or enter command to continue");
  256.         stop_highlight();
  257.         do
  258.         {
  259.             c = vgetc();
  260.             got_int = FALSE;
  261.         } while (c == Ctrl('C')
  262. #ifdef USE_GUI
  263.                                 || c == K_SCROLLBAR || c == K_HORIZ_SCROLLBAR
  264. #endif
  265. #ifdef USE_MOUSE
  266.                                 || c == K_LEFTDRAG   || c == K_LEFTRELEASE
  267.                                 || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
  268.                                 || c == K_RIGHTDRAG  || c == K_RIGHTRELEASE
  269.                                 || c == K_IGNORE     ||
  270.                                 (!mouse_has(MOUSE_RETURN) &&
  271.                                      (c == K_LEFTMOUSE ||
  272.                                       c == K_MIDDLEMOUSE ||
  273.                                       c == K_RIGHTMOUSE))
  274. #endif
  275.                                 );
  276.         mch_breakcheck();
  277. #ifdef USE_MOUSE
  278.         /*
  279.          * Avoid that the mouse-up event causes visual mode to start.
  280.          */
  281.         if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE)
  282.             jump_to_mouse(MOUSE_SETPOS);
  283.         else
  284. #endif
  285.             if (vim_strchr((char_u *)"\r\n ", c) == NULL)
  286.         {
  287.             stuffcharReadbuff(c);
  288.             do_redraw = TRUE;        /* need a redraw even though there is
  289.                                        something in the stuff buffer */
  290.         }
  291. #endif
  292.     }
  293.  
  294.     /*
  295.      * If the user hits ':', '?' or '/' we get a command line from the next
  296.      * line.
  297.      */
  298.     if (c == ':' || c == '?' || c == '/')
  299.     {
  300.         cmdline_row = msg_row;
  301.         skip_redraw = TRUE;            /* skip redraw once */
  302.         do_redraw = FALSE;
  303.     }
  304.  
  305. /*
  306.  * If the window size changed set_winsize() will redraw the screen.
  307.  * Otherwise the screen is only redrawn if 'redraw' is set and no ':' typed.
  308.  */
  309.     tmpState = State;
  310.     State = oldState;                /* restore State before set_winsize */
  311. #ifdef USE_MOUSE
  312.     setmouse();
  313. #endif
  314.     msg_check();
  315.  
  316.     need_wait_return = FALSE;
  317.     emsg_on_display = FALSE;    /* can delete error message now */
  318. #ifdef SLEEP_IN_EMSG
  319.     need_sleep = FALSE;            /* no need to call sleep() anymore */
  320. #endif
  321.     msg_didany = FALSE;            /* reset lines_left at next msg_start() */
  322.     lines_left = -1;
  323.     if (keep_msg != NULL && linetabsize(keep_msg) >=
  324.                                   (Rows - cmdline_row - 1) * Columns + sc_col)
  325.         keep_msg = NULL;            /* don't redisplay message, it's too long */
  326.  
  327.     if (tmpState == SETWSIZE)        /* got resize event while in vgetc() */
  328.     {
  329.         starttermcap();                /* start termcap before redrawing */
  330.         set_winsize(0, 0, FALSE);
  331.     }
  332.     else if (!skip_redraw && (redraw == TRUE || (msg_scrolled && redraw != -1)))
  333.     {
  334.         starttermcap();                /* start termcap before redrawing */
  335.         updateScreen(VALID);
  336.     }
  337.  
  338.     dont_wait_return = TRUE;        /* don't wait again in main() */
  339. }
  340.  
  341. /*
  342.  * Prepare for outputting characters in the command line.
  343.  */
  344.     void
  345. msg_start()
  346. {
  347.     keep_msg = NULL;                        /* don't display old message now */
  348.     keep_msg_highlight = 0;
  349.     if (!msg_scroll && full_screen)            /* overwrite last message */
  350.         msg_pos(cmdline_row, 0);
  351.     else if (msg_didout)                    /* start message on next line */
  352.     {
  353.         msg_outchar('\n');
  354.         cmdline_row = msg_row;
  355.     }
  356.     if (!msg_didany)
  357.         lines_left = cmdline_row;
  358.     msg_didout = FALSE;                        /* no output on current line yet */
  359.     cursor_off();
  360. }
  361.  
  362. /*
  363.  * Move message position. This should always be used after moving the cursor.
  364.  * Use negative value if row or col does not have to be changed.
  365.  */
  366.     void
  367. msg_pos(row, col)
  368.     int        row, col;
  369. {
  370.     if (row >= 0)
  371.         msg_row = row;
  372.     if (col >= 0)
  373.         msg_col = col;
  374. }
  375.  
  376.     void
  377. msg_outchar(c)
  378.     int        c;
  379. {
  380.     char_u        buf[4];
  381.  
  382.     if (IS_SPECIAL(c))
  383.     {
  384.         buf[0] = K_SPECIAL;
  385.         buf[1] = K_SECOND(c);
  386.         buf[2] = K_THIRD(c);
  387.         buf[3] = NUL;
  388.     }
  389.     else
  390.     {
  391.         buf[0] = c;
  392.         buf[1] = NUL;
  393.     }
  394.     msg_outstr(buf);
  395. }
  396.  
  397.     void
  398. msg_outnum(n)
  399.     long        n;
  400. {
  401.     char_u        buf[20];
  402.  
  403.     sprintf((char *)buf, "%ld", n);
  404.     msg_outstr(buf);
  405. }
  406.  
  407.     void
  408. msg_home_replace(fname)
  409.     char_u    *fname;
  410. {
  411.     char_u        *name;
  412.  
  413.     name = home_replace_save(NULL, fname);
  414.     if (name != NULL)
  415.         msg_outtrans(name);
  416.     vim_free(name);
  417. }
  418.  
  419. /*
  420.  * output 'len' characters in 'str' (including NULs) with translation
  421.  * if 'len' is -1, output upto a NUL character
  422.  * return the number of characters it takes on the screen
  423.  */
  424.     int
  425. msg_outtrans(str)
  426.     register char_u *str;
  427. {
  428.     return msg_outtrans_len(str, (int)STRLEN(str));
  429. }
  430.  
  431.     int
  432. msg_outtrans_len(str, len)
  433.     register char_u *str;
  434.     register int   len;
  435. {
  436.     int retval = 0;
  437.  
  438.     while (--len >= 0)
  439.     {
  440.         msg_outstr(transchar(*str));
  441.         retval += charsize(*str);
  442.         ++str;
  443.     }
  444.     return retval;
  445. }
  446.  
  447. /*
  448.  * Output the string 'str' upto a NUL character.
  449.  * Return the number of characters it takes on the screen.
  450.  *
  451.  * If K_SPECIAL is encountered, then it is taken in conjunction with the
  452.  * following character and shown as <F1>, <S-Up> etc.  In addition, if 'all'
  453.  * is TRUE, then any other character which has its 8th bit set is shown as
  454.  * <M-x>, where x is the equivalent character without its 8th bit set.  If a
  455.  * character is displayed in one of these special ways, is also highlighted
  456.  * (its highlight name is '8' in the p_hl variable).
  457.  * This function is used to show mappings, where we want to see how to type
  458.  * the character/string -- webb
  459.  */
  460.     int
  461. msg_outtrans_special(str, all)
  462.     register char_u *str;
  463.     register int    all;    /* <M-a> etc as well as <F1> etc */
  464. {
  465.     int        retval = 0;
  466.     char_u    *string;
  467.     int        c;
  468.     int        modifiers;
  469.  
  470.     set_highlight('8');
  471.     for (; *str; ++str)
  472.     {
  473.         c = *str;
  474.         if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
  475.         {
  476.             modifiers = 0x0;
  477.             if (str[1] == KS_MODIFIER)
  478.             {
  479.                 modifiers = str[2];
  480.                 str += 3;
  481.                 c = *str;
  482.             }
  483.             if (c == K_SPECIAL)
  484.             {
  485.                 c = TO_SPECIAL(str[1], str[2]);
  486.                 str += 2;
  487.                 if (c == K_ZERO)        /* display <Nul> as ^@ */
  488.                     c = NUL;
  489.             }
  490.             if (IS_SPECIAL(c) || modifiers)        /* special key */
  491.             {
  492.                 string = get_special_key_name(c, modifiers);
  493.                 start_highlight();
  494.                 msg_outstr(string);
  495.                 retval += STRLEN(string);
  496.                 stop_highlight();
  497.                 flushbuf();            /* Otherwise gets overwritten by spaces */
  498.                 continue;
  499.             }
  500.         }
  501.         if ((c & 0x80) && all)
  502.         {
  503.             start_highlight();
  504.             MSG_OUTSTR("<M-");
  505.             msg_outstr(transchar(c & 0x7f));
  506.             retval += 2 + charsize(c & 0x7f);
  507.             MSG_OUTSTR(">");
  508.             stop_highlight();
  509.         }
  510.         else
  511.         {
  512.             msg_outstr(transchar(c));
  513.             retval += charsize(c);
  514.         }
  515.     }
  516.     return retval;
  517. }
  518.  
  519. /*
  520.  * print line for :p command
  521.  */
  522.     void
  523. msg_prt_line(s)
  524.     char_u           *s;
  525. {
  526.     register int    si = 0;
  527.     register int    c;
  528.     register int    col = 0;
  529.  
  530.     int             n_extra = 0;
  531.     int             n_spaces = 0;
  532.     char_u            *p = NULL;            /* init to make SASC shut up */
  533.     int             n;
  534.  
  535.     for (;;)
  536.     {
  537.         if (n_extra)
  538.         {
  539.             --n_extra;
  540.             c = *p++;
  541.         }
  542.         else if (n_spaces)
  543.         {
  544.             --n_spaces;
  545.             c = ' ';
  546.         }
  547.         else
  548.         {
  549.             c = s[si++];
  550.             if (c == TAB && !curwin->w_p_list)
  551.             {
  552.                 /* tab amount depends on current column */
  553.                 n_spaces = curbuf->b_p_ts - col % curbuf->b_p_ts - 1;
  554.                 c = ' ';
  555.             }
  556.             else if (c == NUL && curwin->w_p_list)
  557.             {
  558.                 p = (char_u *)"";
  559.                 n_extra = 1;
  560.                 c = '$';
  561.             }
  562.             else if (c != NUL && (n = charsize(c)) > 1)
  563.             {
  564.                 n_extra = n - 1;
  565.                 p = transchar(c);
  566.                 c = *p++;
  567.             }
  568.         }
  569.  
  570.         if (c == NUL)
  571.             break;
  572.  
  573.         msg_outchar(c);
  574.         col++;
  575.     }
  576. }
  577.  
  578. /*
  579.  * output a string to the screen at position msg_row, msg_col
  580.  * Update msg_row and msg_col for the next message.
  581.  */
  582.     void
  583. msg_outstr(s)
  584.     char_u        *s;
  585. {
  586.     int        oldState;
  587.     char_u    buf[20];
  588.  
  589.     /*
  590.      * If there is no valid screen, use fprintf so we can see error messages.
  591.      * If termcap is not active, we may be writing in an alternate console
  592.      * window, cursor positioning may not work correctly (window size may be
  593.      * different, e.g. for WIN32 console).
  594.      */
  595.     if (!msg_check_screen()
  596. #ifdef WIN32
  597.                             || !termcap_active
  598. #endif
  599.                                                 )
  600.     {
  601. #ifdef WIN32
  602.         mch_settmode(0);    /* cook so that \r and \n are handled correctly */
  603. #endif
  604.         fprintf(stderr, (char *)s);
  605.         msg_didout = TRUE;            /* assume that line is not empty */
  606. #ifdef WIN32
  607.         mch_settmode(1);
  608. #endif
  609.         return;
  610.     }
  611.  
  612.     msg_didany = TRUE;            /* remember that something was outputted */
  613.     while (*s)
  614.     {
  615.         /*
  616.          * The screen is scrolled up when:
  617.          * - When outputting a newline in the last row
  618.          * - when outputting a character in the last column of the last row
  619.          *   (some terminals scroll automatically, some don't. To avoid
  620.          *   problems we scroll ourselves)
  621.          */
  622.         if (msg_row >= Rows - 1 && (*s == '\n' || msg_col >= Columns - 1 ||
  623.                               (*s == TAB && msg_col >= ((Columns - 1) & ~7))))
  624.         {
  625.             screen_del_lines(0, 0, 1, (int)Rows, TRUE);    /* always works */
  626.             msg_row = Rows - 2;
  627.             if (msg_col >= Columns)        /* can happen after screen resize */
  628.                 msg_col = Columns - 1;
  629.             ++msg_scrolled;
  630.             need_wait_return = TRUE;    /* may need wait_return in main() */
  631.             if (cmdline_row > 0)
  632.                 --cmdline_row;
  633.             /*
  634.              * if screen is completely filled wait for a character
  635.              */
  636.             if (p_more && --lines_left == 0 && State != HITRETURN)
  637.             {
  638.                 oldState = State;
  639.                 State = ASKMORE;
  640. #ifdef USE_MOUSE
  641.                 setmouse();
  642. #endif
  643.                 msg_moremsg(FALSE);
  644.                 for (;;)
  645.                 {
  646.                     /*
  647.                      * Get a typed character directly from the user.
  648.                      * Don't use vgetc(), it syncs undo and eats mapped
  649.                      * characters.  Disadvantage: Special keys and mouse
  650.                      * cannot be used here, typeahead is ignored.
  651.                      */
  652.                     flushbuf();
  653.                     (void)mch_inchar(buf, 20, -1L);
  654.                     switch (buf[0])
  655.                     {
  656.                     case CR:            /* one extra line */
  657.                     case NL:
  658.                         lines_left = 1;
  659.                         break;
  660.                     case ':':            /* start new command line */
  661.                         stuffcharReadbuff(':');
  662.                         cmdline_row = Rows - 1;        /* put ':' on this line */
  663.                         skip_redraw = TRUE;            /* skip redraw once */
  664.                         dont_wait_return = TRUE;    /* don't wait in main() */
  665.                         /*FALLTHROUGH*/
  666.                     case 'q':            /* quit */
  667.                     case Ctrl('C'):
  668.                         got_int = TRUE;
  669.                         quit_more = TRUE;
  670.                         break;
  671.                     case 'd':            /* Down half a page */
  672.                         lines_left = Rows / 2;
  673.                         break;
  674.                     case ' ':            /* one extra page */
  675.                         lines_left = Rows - 1;
  676.                         break;
  677.                     default:            /* no valid response */
  678.                         msg_moremsg(TRUE);
  679.                         continue;
  680.                     }
  681.                     break;
  682.                 }
  683.                 /* clear the --more-- message */
  684.                 screen_fill((int)Rows - 1, (int)Rows,
  685.                                                    0, (int)Columns, ' ', ' ');
  686.                 State = oldState;
  687. #ifdef USE_MOUSE
  688.                 setmouse();
  689. #endif
  690.                 if (quit_more)
  691.                 {
  692.                     msg_row = Rows - 1;
  693.                     msg_col = 0;
  694.                     return;            /* the string is not displayed! */
  695.                 }
  696.             }
  697.         }
  698.         if (*s == '\n')                /* go to next line */
  699.         {
  700.             msg_didout = FALSE;        /* remember that line is empty */
  701.             msg_col = 0;
  702.             if (++msg_row >= Rows)    /* safety check */
  703.                 msg_row = Rows - 1;
  704.         }
  705.         else if (*s == '\r')        /* go to column 0 */
  706.         {
  707.             msg_col = 0;
  708.         }
  709.         else if (*s == '\b')        /* go to previous char */
  710.         {
  711.             if (msg_col)
  712.                 --msg_col;
  713.         }
  714.         else if (*s == TAB)            /* translate into spaces */
  715.         {
  716.             do
  717.                 msg_screen_outchar(' ');
  718.             while (msg_col & 7);
  719.         }
  720.         else
  721.             msg_screen_outchar(*s);
  722.         ++s;
  723.     }
  724. }
  725.  
  726.     static void
  727. msg_screen_outchar(c)
  728.     int        c;
  729. {
  730.     msg_didout = TRUE;        /* remember that line is not empty */
  731.     screen_outchar(c, msg_row, msg_col);
  732.     if (++msg_col >= Columns)
  733.     {
  734.         msg_col = 0;
  735.         ++msg_row;
  736.     }
  737. }
  738.  
  739.     void
  740. msg_moremsg(full)
  741.     int        full;
  742. {
  743.     /*
  744.      * Need to restore old highlighting when we've finished with it
  745.      * because the output that's paging may be relying on it not
  746.      * changing -- webb
  747.      */
  748.     remember_highlight();
  749.     set_highlight('m');
  750.     start_highlight();
  751.     screen_msg((char_u *)"-- More --", (int)Rows - 1, 0);
  752.     if (full)
  753.         screen_msg((char_u *)" (RET: line, SPACE: page, d: half page, q: quit)",
  754.                                                            (int)Rows - 1, 10);
  755.     stop_highlight();
  756.     recover_old_highlight();
  757. }
  758.  
  759. /*
  760.  * msg_check_screen - check if the screen is initialized.
  761.  * Also check msg_row and msg_col, if they are too big it may cause a crash.
  762.  */
  763.     static int
  764. msg_check_screen()
  765. {
  766.     if (!full_screen || !screen_valid(FALSE))
  767.         return FALSE;
  768.     
  769.     if (msg_row >= Rows)
  770.         msg_row = Rows - 1;
  771.     if (msg_col >= Columns)
  772.         msg_col = Columns - 1;
  773.     return TRUE;
  774. }
  775.  
  776. /*
  777.  * clear from current message position to end of screen
  778.  * Note: msg_col is not updated, so we remember the end of the message
  779.  * for msg_check().
  780.  */
  781.     void
  782. msg_clr_eos()
  783. {
  784.     if (!msg_check_screen()
  785. #ifdef WIN32
  786.                             || !termcap_active
  787. #endif
  788.                                                 )
  789.         return;
  790.     screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, ' ', ' ');
  791.     screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ');
  792. }
  793.  
  794. /*
  795.  * end putting a message on the screen
  796.  * call wait_return if the message does not fit in the available space
  797.  * return TRUE if wait_return not called.
  798.  */
  799.     int
  800. msg_end()
  801. {
  802.     /*
  803.      * if the string is larger than the window,
  804.      * or the ruler option is set and we run into it,
  805.      * we have to redraw the window.
  806.      * Do not do this if we are abandoning the file or editing the command line.
  807.      */
  808.     if (!exiting && msg_check() && State != CMDLINE)
  809.     {
  810.         wait_return(FALSE);
  811.         return FALSE;
  812.     }
  813.     flushbuf();
  814.     return TRUE;
  815. }
  816.  
  817. /*
  818.  * If the written message has caused the screen to scroll up, or if we
  819.  * run into the shown command or ruler, we have to redraw the window later.
  820.  */
  821.     int
  822. msg_check()
  823. {
  824.     if (msg_scrolled || (msg_row == Rows - 1 && msg_col >= sc_col))
  825.     {
  826.         redraw_later(NOT_VALID);
  827.         redraw_cmdline = TRUE;
  828.         return TRUE;
  829.     }
  830.     return FALSE;
  831. }
  832.